#pragma once

#include "stdafx.h"

#ifndef _HAVOK_UTILITIES_
#define _HAVOK_UTILITIES_

// Math and base include
#include <Common/Base/hkBase.h>
#include <Common/Base/System/hkBaseSystem.h>
#include <Common/Base/System/Error/hkDefaultError.h>
#include <Common/Base/Memory/System/Util/hkMemoryInitUtil.h>
#include <Common/Base/Monitor/hkMonitorStream.h>
#include <Common/Base/Memory/System/hkMemorySystem.h>
#include <Common/Base/Memory/Allocator/Malloc/hkMallocAllocator.h>

#include <Physics/Collide/hkpCollide.h>	
#include <Physics/Collide/Agent/ConvexAgent/SphereBox/hkpSphereBoxAgent.h>	
#include <Physics/Collide/Shape/Convex/Box/hkpBoxShape.h>					
#include <Physics/Collide/Shape/Convex/Sphere/hkpSphereShape.h>				
#include <Physics/Collide/Dispatch/hkpAgentRegisterUtil.h>					

#include <Physics/Collide/Query/CastUtil/hkpWorldRayCastInput.h>			
#include <Physics/Collide/Query/CastUtil/hkpWorldRayCastOutput.h>			

#include <Physics/Dynamics/World/hkpWorld.h>								
#include <Physics/Dynamics/Entity/hkpRigidBody.h>							
#include <Physics/Utilities/Dynamics/Inertia/hkpInertiaTensorComputer.h>	

#include <Common/Base/Thread/Job/ThreadPool/Cpu/hkCpuJobThreadPool.h>
#include <Common/Base/Thread/Job/ThreadPool/Spu/hkSpuJobThreadPool.h>
#include <Common/Base/Thread/JobQueue/hkJobQueue.h>

#include <Common/Visualize/hkVisualDebugger.h>
#include <Physics/Utilities/VisualDebugger/hkpPhysicsContext.h>				

#include <stdio.h>

static void HK_CALL errorReport(const char* msg, void* userArgGivenToInit) {
	printf("%s", msg);
}

class HavokUtilities {
public:
	static HavokUtilities* getInstance();

	void registerVisualDebugger();

	void stepSimulation(float deltaTime);	
	void stepVisualDebugger(float deltaTime);

	void createPlane(float x, float y, float z, float width, float height, float thickness);

	hkpWorld* getWorld();
	hkVisualDebugger* getVisualDebugger();

private:
	HavokUtilities(bool visualDebuggerActive);

	virtual ~HavokUtilities(void);
	static HavokUtilities* instance;

	void initHavok();
	void deinitHavok();

	//Variables for memory needs of HAVOK
		hkMemoryRouter* m_pMemoryRouter;
		hkHardwareInfo m_hardwareInfo;
		int m_iTotalNumThreadsUsed;
		hkCpuJobThreadPoolCinfo m_threadPoolCinfo;
		hkJobThreadPool* m_pThreadPool;
		hkJobQueueCinfo m_jobQueuInfo;
		hkJobQueue* m_pJobQueue;

	//World control variables
		hkpWorldCinfo m_worldInfo;
		hkpWorld* m_pPhysicsWorld;

	//Visual debugger
		bool m_bVisualDebuggerActive;
		hkArray<hkProcessContext*> m_arrayPhysicsContext;
		hkVisualDebugger* m_pVisualDebugger;
		hkpPhysicsContext* m_pPhysicsContext;

		float gravityForce;
public :
	bool update(float deltaTime);
	void addFixedSurface(const hkVector4& position, const hkVector4& dimensions);
	void addMovingBoxes(const hkVector4& position, const hkVector4& dimensions);
	static Ogre::Quaternion hkQuatToOgre(hkQuaternion& quat);
};

#endif